package com.neuralnoise;

import java.net.URL;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;

import org.apache.log4j.Logger;
import org.hibernate.Criteria;
import org.hibernate.criterion.Restrictions;

import twitter4j.User;

import com.neuralnoise.hibernate.HibernateSessionFactory;
import com.neuralnoise.hibernate.twitter.Profile;
import com.neuralnoise.hibernate.twitter.ProfileDAO;
import com.neuralnoise.hibernate.twitter.Screen;
import com.neuralnoise.hibernate.twitter.ScreenDAO;

public class TwitterDB extends AbstractDB {

	private Logger logger = Logger.getLogger(this.getClass());
	
	private TwitterDB() { }
	
	public static void clean() {
		HibernateSessionFactory.getSession().beginTransaction();
		ScreenDAO sdao = new ScreenDAO();
		List<Screen> ts = sdao.findAll();
		for (Screen s : ts) {
			sdao.delete(s);
		}
		HibernateSessionFactory.getSession().getTransaction().commit();
	}
	
	public static Screen getScreen(Long id) {
		HibernateSessionFactory.getSession().beginTransaction();
		ScreenDAO sdao = new ScreenDAO();
		Screen screen = sdao.findById(id);
		HibernateSessionFactory.getSession().getTransaction().commit();
		return screen;
	}
		
	public static List<Screen> getScreens() {
		HibernateSessionFactory.getSession().beginTransaction();
		ScreenDAO sdao = new ScreenDAO();
		List<Screen> screens = sdao.findAll();
		HibernateSessionFactory.getSession().getTransaction().commit();
		return screens;
	}
	
	public static Screen addScreen(Long id) {
		HibernateSessionFactory.getSession().beginTransaction();
		ScreenDAO sdao = new ScreenDAO();
		Screen screen = new Screen(id);
		sdao.merge(screen);
		HibernateSessionFactory.getSession().getTransaction().commit();
		return screen;
	}
	
	public static void delScreen(Long id) {
		HibernateSessionFactory.getSession().beginTransaction();
		ScreenDAO sdao = new ScreenDAO();
		Screen screen = sdao.findById(id);
		if (screen != null) {
			sdao.delete(screen);
		}
		HibernateSessionFactory.getSession().getTransaction().commit();
	}
	
	public static Screen toScreen(Long id) {
		HibernateSessionFactory.getSession().beginTransaction();
		ScreenDAO sdao = new ScreenDAO();
		Screen screen = sdao.findById(id);
		if (screen == null) {
			screen = new Screen(id);
			sdao.merge(screen);
		}
		HibernateSessionFactory.getSession().getTransaction().commit();
		return screen;
	}
	
	
	public static Profile getProfile(Long screen) {
		HibernateSessionFactory.getSession().beginTransaction();
		ProfileDAO pdao = new ProfileDAO();
		Profile profile = pdao.findById(screen);
		HibernateSessionFactory.getSession().getTransaction().commit();
		return profile;
	}
	
	public static Collection<Profile> getProfiles() {
		HibernateSessionFactory.getSession().beginTransaction();
		ProfileDAO pdao = new ProfileDAO();
		Collection<Profile> profiles = pdao.findAll();
		HibernateSessionFactory.getSession().getTransaction().commit();
		return profiles;
	}

	public static void addProfile(Long screen, User u) {
		HibernateSessionFactory.getSession().beginTransaction();
		ProfileDAO pdao = new ProfileDAO();

		URL url = u.getURL();
		String surl = (url == null ? null : url.toString());

		Profile p = new Profile(screen, u.getScreenName(), u.getName(),
				u.getLocation(), u.getLang(),
				surl, u.getStatusesCount(), u.getFollowersCount(), u.getFavouritesCount(), u.getFriendsCount());

		pdao.merge(p);
		HibernateSessionFactory.getSession().getTransaction().commit();
	}
	
	public static Collection<Screen> getFriendsOf(Long id) {
		HibernateSessionFactory.getSession().beginTransaction();
		Criteria criteria = HibernateSessionFactory.getSession().createCriteria(Screen.class);
		criteria = criteria.createAlias("screensForSubject", "friendsOf");
		criteria = criteria.add(Restrictions.eq("friendsOf.id", id));
		Collection<Screen> friends = criteria.list();
		HibernateSessionFactory.getSession().getTransaction().commit();
		return friends;
	}
	
	public static Screen addFriend(Long id, Long friend) {
		Screen screen = toScreen(id);
		Screen tfriend = toScreen(friend);
		HibernateSessionFactory.getSession().beginTransaction();
		ScreenDAO sdao = new ScreenDAO();
		screen.getScreensForObject().add(tfriend);
		sdao.merge(screen);
		HibernateSessionFactory.getSession().getTransaction().commit();
		return tfriend;
	}
	
	public static Collection<Screen> addFriends(Long id, Collection<Long> friends) {
		Screen screen = toScreen(id);
		Collection<Screen> tfriends = new LinkedList<Screen>();
		for (Long friend : friends) {
			tfriends.add(toScreen(friend));
		}
		HibernateSessionFactory.getSession().beginTransaction();
		ScreenDAO sdao = new ScreenDAO();
		for (Screen tfriend : tfriends) {
			screen.getScreensForObject().add(tfriend);
			sdao.merge(screen);
		}
		HibernateSessionFactory.getSession().getTransaction().commit();
		return tfriends;
	}
	
	public static Collection<Screen> addFollowers(Long id, Collection<Long> followers) {
		Screen screen = toScreen(id);
		Collection<Screen> tfollowers = new LinkedList<Screen>();
		for (Long follower : followers) {
			tfollowers.add(toScreen(follower));
		}
		HibernateSessionFactory.getSession().beginTransaction();
		ScreenDAO sdao = new ScreenDAO();
		for (Screen tfollower : tfollowers) {
			screen.getScreensForSubject().add(tfollower);
			sdao.merge(screen);
		}
		HibernateSessionFactory.getSession().getTransaction().commit();
		return tfollowers;
	}
	
}
